#ifndef ILLIB_VECTOR_H_
#define ILLIB_VECTOR_H_

#include <illib/Buffer.h>
#include <memory.h>

namespace illib{
	namespace Buffer{
		template <typename T> class Iterator;
		template <typename T> class Vector : public Static{
		public:
			typedef Vector<T> VectorType;
			typedef Iterator<T> IteratorType;
			typedef T ElementType;
		protected:
		public:
			Vector() :
				Static(0, 0)
			{

			}
			Vector(Allocator &allocator, size_t length) :
				Static(allocator, length * sizeof(T))
			{

			}
			Vector(T * block, size_t length) :
				Static(reinterpret_cast<uint8_t *>(block), length * sizeof(T))
			{

			}

			~Vector(){

			}
			void clear(){
				resize(0);
			}
			T* start(){
				return reinterpret_cast<T*>(block_);
			}
			bool resize(size_t count){
				return this->Static::resize(count * sizeof(T), true);
			}
			void setup(T* block, size_t length) {
				Static::setup(reinterpret_cast<uint8_t *>(block), length * sizeof(T));
			}
			T* add(size_t index, size_t count=1){
				if(index > length()) return 0;
				size_t oldlength = length();
				if (!resize(oldlength + count)) return 0;
				size_t offset = index * sizeof(T);
				size_t moveby = count * sizeof(T);
				size_t affected = (oldlength-index) * sizeof(T);
				if((index < oldlength) && (affected)){
					void * dst = Static::start() + offset + moveby;
					void * src = Static::start() + offset;
					memmove(dst, src, affected);
				}
				return reinterpret_cast<T*>(Static::start() + offset);
			}
			T* get(size_t index){
				if(index >= length()) return 0;
				return reinterpret_cast<T*>(Static::start() + (index * sizeof(T)));
			}
			bool remove(size_t index, size_t count){
				if(index >= length()) return false;
				if(index + (count-1) >= length()) return false;
				size_t offset = index * sizeof(T);
				size_t moveby = count * sizeof(T);
				size_t affected = (length()-index) * sizeof(T);
				void * src = Static::start() + offset + moveby;
				void * dst = Static::start() + offset;
				memmove(dst, src, affected);
				resize(length() - count);
				return true;
			}
			size_t length(){
				return size()/sizeof(T);
			}
		};
		template <typename T> class Iterator{
		public:
			typedef Vector<T> VectorType;
			typedef Iterator<T> IteratorType;
			typedef T ElementType;
		protected:
			VectorType * vector_;
			size_t index_;
		public:
			Iterator(VectorType & vector, bool end=false) :
				vector_(&vector)
			{
				if(end) index_ = vector_->length()-1;
				else index_=0;
			}
			void setup(VectorType & vector, bool end=false)
			{
				vector_ = &vector;
				if(end) index_ = vector_->length()-1;
				else index_=0;
			}
			Iterator() :
				vector_(0),
				index_(0)
			{
			}
			T* current(){
				if (index_ >= vector_->length()) return 0;
				return vector_->get(index_);
			}
			T* next(){
				if (index_ >= vector_->length()) return 0;
				index_++;
				return current();
			}
			T* prev(){
				if (index_ >= vector_->length()) return 0;
				index_--;
				return current();
			}
			size_t index(){
				return index_;
			}
			T* jump(int jump){
				if(jump == 0) return current();
				if(jump > 0) {
					if (index_ >= vector_->length()) return 0;
					if ((index_+jump)-1 >= vector_->length()) return 0;
					index_ += jump;
					return current();
				}
				if (index_ >= vector_->length()) return 0;
				if ((index_-jump)-1 >= vector_->length()) return 0;
				index_ -= jump;
				return current();
			}
		};
	};
}
#endif /* ILLIB_VECTOR_H_ */
